package com.mlethe.library.multi.api;

import android.content.Context;
import android.text.TextUtils;

import androidx.annotation.NonNull;

import com.mlethe.library.multi.api.listener.OnActionCallback;
import com.tencent.connect.UnionInfo;
import com.tencent.connect.UserInfo;
import com.tencent.connect.auth.QQToken;
import com.tencent.connect.common.Constants;
import com.tencent.tauth.DefaultUiListener;
import com.tencent.tauth.IUiListener;
import com.tencent.tauth.Tencent;
import com.tencent.tauth.UiError;

import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

/**
 * QQ 授权登录和分享回调处理
 *
 * @author Mlethe
 * @date 2024/12/20
 */
final class QQEventHandler implements IUiListener {

    /**
     * QQ 授权登录对象
     */
    private Tencent mTencent;

    /**
     * 回调监听
     */
    private OnActionCallback mOnActionCallback;

    public QQEventHandler(@NonNull Tencent tencent, OnActionCallback callback) {
        this.mTencent = tencent;
        this.mOnActionCallback = callback;
    }

    /**
     * 释放内存
     */
    private void release() {
        mTencent = null;
        mOnActionCallback = null;
    }

    /**
     * @param response 以下是响应的数据
     *                 {
     *                 "ret":0,
     *                 "pay_token":"xxxxxxxxxxxxxxxx",
     *                 "pf":"openmobile_android",
     *                 "expires_in":"7776000",
     *                 "openid":"xxxxxxxxxxxxxxxxxxx",
     *                 "pfkey":"xxxxxxxxxxxxxxxxxxx",
     *                 "msg":"sucess",
     *                 "access_token":"xxxxxxxxxxxxxxxxxxxxx"
     *                 }
     */
    @Override
    public void onComplete(Object response) {
        MultiApi instance = MultiApi.getInstance();
        instance.i("QQ handler onComplete. response=" + response);
        instance.release();
        Context context = instance.getContext();
        Tencent tencent = mTencent;
        OnActionCallback callback = mOnActionCallback;
        MultiMedia media = MultiMedia.QQ;
        release();
        if (callback == null) {
            return;
        }
        if (null == response) {
            onFailure(callback, media, -9006, context.getString(R.string.multi_api_result_data_empty));
            return;
        }
        JSONObject jsonResponse = (JSONObject) response;
        if (jsonResponse.length() == 0) {
            onFailure(callback, media, -9006, context.getString(R.string.multi_api_result_data_empty));
            return;
        }
        int ret = jsonResponse.optInt("ret");
        String msg = jsonResponse.optString("msg");
        if (ret != 0) {
            onFailure(callback, media, ret, msg);
            return;
        }
        if (callback.getAction() == 1) {
            String token = jsonResponse.optString(Constants.PARAM_ACCESS_TOKEN);
            String expiration = jsonResponse.optString(Constants.PARAM_EXPIRES_IN);
            String openId = jsonResponse.optString(Constants.PARAM_OPEN_ID);
            instance.i("QQ auth success. data=" + jsonResponse);
            if (!TextUtils.isEmpty(token) && !TextUtils.isEmpty(expiration)
                    && !TextUtils.isEmpty(openId)) {
                tencent.setAccessToken(token, expiration);
                tencent.setOpenId(openId);
            } else {
                onFailure(callback, media, -9001, context.getString(R.string.multi_api_access_token_acquisition_failed));
                return;
            }
            if (tencent.isSessionValid()) {
                QQToken qqToken = tencent.getQQToken();
                if (callback != null && !callback.isGetUserInfo) {
                    Map<String, String> map = new HashMap<>();
                    map.put("openid", openId);
                    map.put("accessToken", token);
                    map.put("expiration", expiration);
                    getUnionId(context, instance, qqToken, map, callback);
                    return;
                }
                UserInfo info = new UserInfo(context, tencent.getQQToken());
                instance.i("QQ getUserInfo start request.");
                info.getUserInfo(new DefaultUiListener() {
                    @Override
                    public void onComplete(Object resp) {
                        instance.i("QQ getUserInfo success response. data=" + resp);
                        if (null == resp) {
                            onFailure(callback, media, -9003, context.getString(R.string.multi_api_obtain_user_information_fail));
                            return;
                        }
                        JSONObject jsonResp = (JSONObject) resp;
                        int ret;
                        String msg;
                        try {
                            ret = jsonResp.getInt("ret");
                            msg = jsonResp.getString("msg");
                        } catch (Throwable t) {
                            onFailure(callback, media, -9900, t.getMessage());
                            return;
                        }
                        /**
                         * ret	返回码，0: 正确返回
                         * msg	如果ret<0，会有相应的错误信息提示，返回数据全部用UTF-8编码。
                         * nickname	用户在QQ空间的昵称。
                         * figureurl	大小为30×30像素的QQ空间头像URL。
                         * figureurl_1	大小为50×50像素的QQ空间头像URL。
                         * figureurl_2	大小为100×100像素的QQ空间头像URL。
                         * figureurl_qq_1	大小为40×40像素的QQ头像URL。
                         * figureurl_qq_2	大小为100×100像素的QQ头像URL。需要注意，不是所有的用户都拥有QQ的100x100的头像，但40x40像素则是一定会有。
                         * gender	性别。 如果获取不到则默认返回"男"
                         * gender_type	性别类型。默认返回2。
                         * province	省
                         * city	市
                         * year	年
                         * is_yellow_vip	标识用户是否为黄钻用户（0：不是；1：是）。
                         * vip	标识用户是否为黄钻用户（0：不是；1：是）
                         * yellow_vip_level	黄钻等级
                         * level	黄钻等级
                         * is_yellow_year_vip 标识是否为年费黄钻用户（0：不是； 1：是）
                         *
                         * 2022年1月8日后，上述接口country（国家）字段返回("中国")，province（省份）字段返回("广东")，city（城市）字段返回("深圳")，year（年份）字段返回(1990) （即全部返回默认值，不返回用户真实资料信息）；
                         */
                        if (ret == 0) {
                            Map<String, String> map = new HashMap<>();
                            map.put("openid", openId);
                            map.put("accessToken", token);
                            map.put("expiration", expiration);
                            map.put("nickname", jsonResp.optString("nickname"));
                            String figureurl = jsonResp.optString("figureurl_qq_2");
                            if (figureurl.isEmpty() || "null".equalsIgnoreCase(figureurl)) {
                                figureurl = jsonResp.optString("figureurl_qq_1");
                            }
                            map.put("iconUrl", figureurl);
                            String gender = jsonResp.optString("gender");
                            int sex = 0;
                            if ("男".equals(gender)) {
                                sex = 1;
                            } else if ("女".equals(gender)) {
                                sex = 2;
                            }
                            map.put("sex", sex + "");
                            map.put("is_yellow_year_vip", jsonResp.optString("is_yellow_year_vip"));
                            map.put("yellow_vip_level", jsonResp.optString("yellow_vip_level"));
                            // 获取unionid
                            getUnionId(context, instance, qqToken, map, callback);
                        } else {
                            onFailure(callback, media, ret, msg);
                        }
                    }

                    @Override
                    public void onError(UiError uiError) {
                        int errorCode = -9000;
                        String errorMsg = "";
                        if (uiError != null) {
                            errorCode = uiError.errorCode;
                            errorMsg = uiError.errorMessage;
                        }
                        if (TextUtils.isEmpty(errorMsg)) {
                            errorMsg = context.getString(R.string.multi_api_privilege_grant_failed);
                        }
                        instance.e("QQ getUserInfo fail response. code=" + errorCode + ", message=" + errorMsg);
                        onFailure(callback, media, errorCode, errorMsg);
                    }

                    @Override
                    public void onCancel() {
                        QQEventHandler.this.onCancel(callback, media);
                    }
                });
            } else {
                onFailure(callback, media, -9002, context.getString(R.string.multi_api_access_token_expired));
            }
        } else {
            instance.i("QQ share success.");
            Map<String, String> map = new HashMap<>();
            QQEventHandler.this.onComplete(callback, media, map);
        }
    }

    @Override
    public void onError(UiError uiError) {
        MultiApi instance = MultiApi.getInstance();
        instance.release();
        OnActionCallback callback = mOnActionCallback;
        release();
        int errorCode = -9000;
        String errorMsg = "";
        if (uiError != null) {
            errorCode = uiError.errorCode;
            errorMsg = uiError.errorMessage;
        }
        if (TextUtils.isEmpty(errorMsg)) {
            Context context = instance.getContext();
            errorMsg = context.getString(R.string.multi_api_privilege_grant_failed);
        }
        instance.e("QQ handler fail. code=" + errorCode + ",message=" + errorMsg);
        onFailure(callback, MultiMedia.QQ, errorCode, errorMsg);
    }

    @Override
    public void onCancel() {
        MultiApi instance = MultiApi.getInstance();
        instance.release();
        instance.i("QQ handler cancel.");
        OnActionCallback callback = mOnActionCallback;
        release();
        onCancel(callback, MultiMedia.QQ);
    }

    @Override
    public void onWarning(int i) {

    }

    /**
     * 获取 unionId
     *
     * @param context
     * @param qqToken
     * @param map
     * @param callback
     */
    private void getUnionId(Context context, MultiApi instance, QQToken qqToken, Map<String, String> map, OnActionCallback callback) {
        MultiMedia media = MultiMedia.QQ;
        UnionInfo unionInfo = new UnionInfo(context, qqToken);
        instance.i("QQ getUnionId start request.");
        unionInfo.getUnionId(new DefaultUiListener() {
            @Override
            public void onComplete(Object json) {
                instance.i("QQ getUnionId success response. data=" + json);
                if (null == json) {
                    QQEventHandler.this.onComplete(callback, media, map);
                    return;
                }
                JSONObject jsonObject = (JSONObject) json;
                try {
                    map.put("unionid", jsonObject.getString("unionid"));
                } catch (Throwable t) {
                    t.printStackTrace();
                }
                QQEventHandler.this.onComplete(callback, media, map);
            }

            @Override
            public void onError(UiError uiError) {
                int errorCode = -1000;
                String message = "";
                if (uiError != null) {
                    errorCode = uiError.errorCode;
                    message = uiError.errorMessage;
                }
                if (errorCode == 100048) {
                    // 未申请unionID接口调用权限，请邮件申请
                }
                instance.e("QQ getUnionId fail response：code=" + errorCode + ", message=" + message);
                QQEventHandler.this.onComplete(callback, media, map);
            }

            @Override
            public void onCancel() {
                QQEventHandler.this.onComplete(callback, media, map);
            }
        });
    }

    /**
     * 完成回调监听
     *
     * @param callback
     * @param media
     * @param map
     */
    private void onComplete(OnActionCallback callback, @NonNull MultiMedia media, @NonNull Map<String, String> map) {
        if (callback == null) {
            return;
        }
        callback.onComplete(media, map);
    }

    /**
     * 取消回调监听
     *
     * @param callback
     * @param media
     */
    private void onCancel(OnActionCallback callback, @NonNull MultiMedia media) {
        if (callback == null) {
            return;
        }
        callback.onCancel(media);
    }

    /**
     * 失败回调监听
     *
     * @param callback
     * @param media
     * @param code
     */
    private void onFailure(OnActionCallback callback, @NonNull MultiMedia media, int code, String msg) {
        if (callback == null) {
            return;
        }
        callback.onFailure(media, code, msg);
    }
}
